package cn.jdemo.core.hotload;

import java.io.*;

/**
 * 热加载
 * 唯一类:一个classloader+一个全类名
 * 设置: -XX:+TraceClassLoading -XX:+TraceClassUnloading
 *
 * // 这个项目是个热加载示例
 * <a href="https://gitee.com/osbuild/hotload-classloader"></>
 */
public class FileClassLoader extends ClassLoader{

    /**
     * ...
     * [Loaded cn.jdemo.core.testcase.Test from __JVM_DefineClass__]
     * cn.jdemo.core.hotload.FileClassLoader@12bb4df8
     * class cn.jdemo.core.testcase.Test
     * [Loaded cn.jdemo.core.testcase.Test from __JVM_DefineClass__]
     * cn.jdemo.core.hotload.FileClassLoader@7a7b0070
     * class cn.jdemo.core.testcase.Test
     * ...
     */
    public static void main(String[] args) throws Exception {
        //创建自定义文件类加载器
        FileClassLoader loader = new FileClassLoader("D:/gm/code/jdemo/");
        Class<?> class1 = loader.loadClass("cn.jdemo.core.testcase.Test");
        System.out.println(class1.getClassLoader());
        System.out.println(class1.toString());

        FileClassLoader loader2 = new FileClassLoader("D:/gm/code/jdemo/other/");
        Class<?> class2 = loader2.loadClass("cn.jdemo.core.testcase.Test");
        System.out.println(class2.getClassLoader());
        System.out.println(class2.toString());
    }

    private String rootPath;
    public FileClassLoader(String rootPath) {
        super();
        this.rootPath = rootPath;
    }

    @Override
    protected Class<?> findClass(String name) throws ClassNotFoundException {
        /* 加载class内容 */
        byte[] bytes = loadClassData(name);
        /* 定义class文件结构 */
        return defineClass(name, bytes, 0, bytes.length);
    }


    private byte[] loadClassData(String name) {
        try {
            name = name.replace(",", "//");
            String[] split = name.split("\\.");
            FileInputStream fileInputStream = new FileInputStream(new File(rootPath + split[split.length-1] + ".class"));
            ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
            int b = 0;
            while ((b = fileInputStream.read()) != -1) {
                byteArrayOutputStream.write(b);
            }
            fileInputStream.close();
            return byteArrayOutputStream.toByteArray();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }


}
